/**
 *
 */
package com.bn.feeds.tools;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.math.NumberUtils;

import com.bn.feedMaster.FeedProcessException;
import com.bn.feeds.MasterFeedConfiguration;

import atg.core.util.StringUtils;
import atg.nucleus.GenericService;
import atg.repository.MutableRepository;
import atg.repository.MutableRepositoryItem;
import atg.repository.Repository;
import atg.repository.RepositoryException;
import atg.repository.RepositoryItem;


// TODO: Auto-generated Javadoc
/**
 * The Class BaseRepositoryTools.
 */
public abstract class BaseRepositoryTools extends GenericService implements
		FeedRepositoryTool {

    /** The string properties. */
    private List<String> stringProperties;

    /** The boolean properties. */
    private List<String> booleanProperties;

    /** The int properties. */
    private List<String> intProperties;

    /** The date properties. */
    private List<String> dateProperties;

    /** The item type list properties map. */
    private Map<String, String> itemTypeListPropertiesMap;

    /** The list type properties. */
    private List<String> listTypeProperties;
    
    private String itemDescriptorName;
    
    private String subTypeDefinationProperty;
    

    /** The item type single properties map. */
    private Map<String, String> itemTypeSinglePropertiesMap;
	private static final String CATALOG_ITEM_DESCRIPTOR="catalog";
	private static final String CATEGORY_ITEM_DESCRIPTOR="category";
	 private List<String> doubleProperties;
	 
	private boolean enableExistingItmNtProcess;

	   /** The repository. */
    private Repository repository;
    
    private List<String> ignoreIfDataExistsProperties;

	/* (non-Javadoc)
	 * @see com.tru.feeds.tools.FeedRepositoryTool#cleanUpData(atg.repository.MutableRepository, java.lang.String)
	 */
	@Override
	public boolean cleanUpData(MutableRepository repository,
			String itemDescriptor) throws FeedProcessException {
		// TODO Auto-generated method stub
		return false;
	}
	
	
	public List<String> processRecord(MasterFeedConfiguration config,
            String[] dataRow, String[] header, int idColumnIndex,
            Map<String, Integer> repositoryPropertiesToTokenIndexMap,
            Map<String, Integer> repositoryItemPropertiesToTokenIndexMap,Map<String, String> productProcessedMap, Map<String, Integer> mandatoryPropertiesMap)
            throws FeedProcessException {
	   List<String> errorList = new ArrayList<String>();
   if(!validateMandatoryProperties(config, mandatoryPropertiesMap, dataRow, errorList)){
       return errorList;
       }
          if(isLoggingDebug()){
			logDebug("SkuRepositoryTools::>processRecord()::BEGIN");
		  }
         MutableRepository mutableRepository =  config.getRepository();
         Repository repository = config.getPrdRepository();
		 try {
			 String itemId = dataRow[idColumnIndex];
                RepositoryItem item = null;
                Integer typeIndex = repositoryPropertiesToTokenIndexMap.get(getSubTypeDefinationProperty());
                String itemDescriptorName = getItemDescriptorName();
                String type = null;

                if (typeIndex != null) {
                    type = dataRow[typeIndex].trim().toLowerCase();
                }

                if (isLoggingDebug()) {
                    logDebug("ProductRepositoryTools::>processRecord()::Product Type in feed : " + type + " . Setting product type to default :: " + itemDescriptorName);
                }
			 if(!StringUtils.isBlank(itemId)){
				itemId = itemId.trim();
				MutableRepositoryItem mutabletem=null;
				 if(isLoggingDebug()){
						logDebug("SkuRepositoryTools::>processRecord()::ItemDescriptor type: "+getItemDescriptorName());
					}
				item = repository.getItem(itemId, itemDescriptorName);
				if (item != null){
					 if(isLoggingDebug()){
							logDebug("SkuRepositoryTools::>processRecord()::item already exists in Repository with id:"+item.getRepositoryId()+" Fetching for update");
						}
					mutabletem = (MutableRepositoryItem)item;
					setPropertiesToItem(mutableRepository,repository, mutabletem, repositoryPropertiesToTokenIndexMap, repositoryItemPropertiesToTokenIndexMap,dataRow, itemDescriptorName, errorList);
					mutableRepository.updateItem(mutabletem);
				} else {
					if(isLoggingDebug()){
						logDebug("SkuRepositoryTools::>processRecord()::item does not exists in Repository with id:"+itemId+" creating new item");
					}
					mutabletem = mutableRepository.createItem(itemId, itemDescriptorName);
				setPropertiesToItem(mutableRepository,repository, mutabletem, repositoryPropertiesToTokenIndexMap,repositoryItemPropertiesToTokenIndexMap, dataRow, itemDescriptorName, errorList);
				mutableRepository.addItem(mutabletem);
				}
			 }else{
	             if(isLoggingDebug()){
	                 logDebug("CouponRepositoryTools::>processRecord()::Value of Id property in feed is null");
	             }
	             throw new FeedProcessException("Value of Id property in feed is null, cannot create/update Item so skipping the row");
			 }
		 } catch(RepositoryException e){
			 if(isLoggingDebug()){
					logDebug("SkuRepositoryTools::>processRecord():: Error occurred while fetching Item:"+dataRow[idColumnIndex]);
				}
	         throw new FeedProcessException(e);
	     }  catch(NumberFormatException e){
	         throw new FeedProcessException(e);
	     }
		 if(isLoggingDebug()){
				logDebug("SkuRepositoryTools::>processRecord()::END");
			}
		 return errorList;
}

	
	

	protected boolean validateMandatoryProperties(MasterFeedConfiguration config,Map<String, Integer> mandatoryPropertiesMap, String[] dataRow, List<String> errorList) {
	    if(isLoggingDebug()){
            logDebug("BaseRepositoryTools::>validateMandatoryProperties()::BEGIN");
        }
	    String mandtryPropertyValue = null;
	    List<String> mandatoryProperties = null;
	    mandatoryProperties = config.getMandatoryProperties();
        ArrayList<String> mandatoryErrorList = new ArrayList<String>();
       if(mandatoryProperties!=null && !mandatoryProperties.isEmpty()){
          for(String mandatoryProperty : mandatoryProperties){
              if(mandatoryPropertiesMap.get(mandatoryProperty)!=null){
                  mandtryPropertyValue = dataRow[mandatoryPropertiesMap.get(mandatoryProperty)];
                  if(StringUtils.isBlank(mandtryPropertyValue)){
                      mandatoryErrorList.add(mandatoryProperty);
                  }
              }else{
                  mandatoryErrorList.add(mandatoryProperty);
              }
            }
       }
       if(mandatoryErrorList.size()>0){
           if(isLoggingError()){
               logError("Value missing in Feed for Mandatory properties:" + mandatoryErrorList.toString()+" for row: "+Arrays.toString(dataRow));
           }
           errorList.add("Value missing in Feed for Mandatory properties:" + mandatoryErrorList.toString()+" for row: "+Arrays.toString(dataRow));
           return false;
           }
       if(isLoggingDebug()){
               logDebug("BaseRepositoryTools::>validateMandatoryProperties()::END || returning value:"+true);
           }
       return true;
    }


	/**
     * Sets the properties to item.
     *
     * @param mutableRespository
     *            the repository
     * @param item
     *            the item
     * @param repositoryPropertiesToTokenIndexMap
     *            the repository properties to token index map
     * @param repositoryItemPropertiesToTokenIndexMap
     *            the repository item properties to token index map
     * @param dataRow
     *            the data row
     * @param itemDescriptorName
     *            the item descriptor name
     * @throws FeedProcessException
     *             the feed process exception
     */
    protected void setPropertiesToItem(MutableRepository mutableRespository, Repository repository, MutableRepositoryItem item, Map<String, Integer>repositoryPropertiesToTokenIndexMap, Map<String, Integer> repositoryItemPropertiesToTokenIndexMap, String[] dataRow, String itemDescriptorName, List<String> errorList ) throws FeedProcessException{
        if(isLoggingDebug()){
            logDebug("BaseRepositoryTools::>setPropertiesToItem()::BEGIN");
        }
        if(getStringProperties()!=null && getStringProperties().size()>0){
            setStringTypeProperties(item, repositoryPropertiesToTokenIndexMap, dataRow,getStringProperties());
        }
        if(getBooleanProperties()!=null && getBooleanProperties().size()>0){
            setBooleanTypeProperties(item, repositoryPropertiesToTokenIndexMap, dataRow,getBooleanProperties());
        }
        if(getIntProperties()!=null && getIntProperties().size()>0){
            setIntegerTypeProperties(item, repositoryPropertiesToTokenIndexMap, dataRow,getIntProperties());
        }
        if(getDateProperties()!=null && getDateProperties().size()>0){
            try {
                setDateTypeProperties(item, repositoryPropertiesToTokenIndexMap, dataRow,getDateProperties());
            } catch (FeedProcessException e) {
            	 logError(e);
               throw new FeedProcessException("An Error occured while setting Date type properties"+e.getMessage());
            }
        }
        if (getListTypeProperties() != null && !getListTypeProperties().isEmpty()) {
            setListTypeProperties(mutableRespository, item, repositoryPropertiesToTokenIndexMap, dataRow, getListTypeProperties(), itemDescriptorName);
        }
        if (getDoubleProperties() != null && !getDoubleProperties().isEmpty()) {
            setDoubleTypeProperties(item, repositoryPropertiesToTokenIndexMap, dataRow, getDoubleProperties());
        }
        if(getItemTypeSinglePropertiesMap()!=null && getItemTypeSinglePropertiesMap().size()>0){
            setItemTypeSingleProperties(mutableRespository, repository, item, repositoryItemPropertiesToTokenIndexMap,getItemTypeSinglePropertiesMap(), dataRow, errorList);
        }
        if(getItemTypeListPropertiesMap()!=null && getItemTypeListPropertiesMap().size()>0){
            setItemTypeListProperties(mutableRespository, repository, item, repositoryItemPropertiesToTokenIndexMap,getItemTypeListPropertiesMap(), dataRow, errorList);
        }
        if(isLoggingDebug()){
            logDebug("BaseRepositoryTools::>setPropertiesToItem()::END");
        }
    }
	/**
	 * Sets the string type properties.
	 *
	 * @param repository
	 *            the repository
	 * @param item
	 *            the item
	 * @param repositoryPropertiesToTokenIndexMap
	 *            the repository properties to token index map
	 * @param dataRow
	 *            the data row
	 * @param stringProperties
	 *            the string properties
	 * @param itemDescriptorName
	 *            the item descriptor name
	 */
	protected void setStringTypeProperties(MutableRepositoryItem item, Map<String, Integer>repositoryPropertiesToTokenIndexMap, String[] dataRow,List<String> stringProperties){
		if(isLoggingDebug()){
			logDebug("BaseRepositoryTools::>setStringTypeProperties()::Begin");
		}
		String sProp = null;
		for (String stringProperty : stringProperties) {
		    if(isLoggingDebug()){
	            logDebug("BaseRepositoryTools::>setStringTypeProperties():: Setting property:"+ stringProperty);
	        }
			if(repositoryPropertiesToTokenIndexMap.get(stringProperty)!=null){
				sProp=dataRow[repositoryPropertiesToTokenIndexMap.get(stringProperty)];
				if(!StringUtils.isBlank(sProp)){
				    if(isLoggingDebug()){
		                logDebug("BaseRepositoryTools::>setStringTypeProperties():: String value in feed:"+ sProp);
		            }
				    if(null != getIgnoreIfDataExistsProperties() && getIgnoreIfDataExistsProperties().contains(stringProperty) && !StringUtils.isBlank((String)item.getPropertyValue(stringProperty))){
				    	if(isLoggingDebug()){
			                logDebug("BaseRepositoryTools::>setStringTypeProperties():: skipping record update : data already exists for the property:"+stringProperty+":"+ sProp);
			            }
				    	continue;
				    }
					item.setPropertyValue(stringProperty, sProp.trim());
				} else{
				    if(isLoggingDebug()){
                        logDebug("BaseRepositoryTools::>setStringTypeProperties():: Value for String property :"+ stringProperty + ", is null in feed, so not setting");
                    }
				}
			} else{
			    if(isLoggingError()){
			        logError("BaseRepositoryTools::>setStringTypeProperties():: column for String property:"+ stringProperty+" not present in feed file");
			    }
			}

		}
		if(isLoggingDebug()){
			logDebug("BaseRepositoryTools::>setStringTypeProperties()::End");
		}
	}

	/**
	 * Sets the boolean type properties.
	 *
	 * @param repository
	 *            the repository
	 * @param item
	 *            the item
	 * @param repositoryPropertiesToTokenIndexMap
	 *            the repository properties to token index map
	 * @param dataRow
	 *            the data row
	 * @param booleanProperties
	 *            the boolean properties
	 * @param itemDescriptorName
	 *            the item descriptor name
	 */
	protected void setBooleanTypeProperties(MutableRepositoryItem item, Map<String, Integer>repositoryPropertiesToTokenIndexMap, String[] dataRow,List<String> booleanProperties){
		if(isLoggingDebug()){
			logDebug("BaseRepositoryTools::>setBooleanTypeProperties()::BEGIN");
		}
		String sProp = null;
		for (String booleanProperty : booleanProperties) {
		    if(isLoggingDebug()){
	            logDebug("BaseRepositoryTools::>setBooleanTypeProperties():: Setting property: "+booleanProperty);
	        }
			if(repositoryPropertiesToTokenIndexMap.get(booleanProperty)!=null){
			sProp=dataRow[repositoryPropertiesToTokenIndexMap.get(booleanProperty)];
			if(!StringUtils.isBlank(sProp)){
				if(sProp.equalsIgnoreCase("Y") || sProp.equalsIgnoreCase("YES") || sProp.equalsIgnoreCase("1")|| sProp.equalsIgnoreCase("true")){
	                if(isLoggingDebug()){
	                    logDebug("BaseRepositoryTools::>setBooleanTypeProperties():: Setting value for property: "+booleanProperty+" to:"+ true);
	                }
					item.setPropertyValue(booleanProperty, Boolean.TRUE);
				}else{
				    if(isLoggingDebug()){
                        logDebug("BaseRepositoryTools::>setBooleanTypeProperties():: Setting value for property: "+booleanProperty+" to:"+ false);
                    }
					item.setPropertyValue(booleanProperty, Boolean.FALSE);
				}

			} else {
			    if(isLoggingDebug()){
	                logDebug("BaseRepositoryTools::>setBooleanTypeProperties():: Value for property: "+booleanProperty+" is null in feed, so not setting");
	            }
			}
		} else {
		    if(isLoggingError()){
	            logError("BaseRepositoryTools::>setBooleanTypeProperties():: column for property:"+booleanProperty+" not present in feed file");
	        }
		}
		}
		if(isLoggingDebug()){
			logDebug("BaseRepositoryTools::>setBooleanTypeProperties()::END");
		}
	}

	/**
	 * Sets the integer type properties.
	 *
	 * @param repository
	 *            the repository
	 * @param item
	 *            the item
	 * @param repositoryPropertiesToTokenIndexMap
	 *            the repository properties to token index map
	 * @param dataRow
	 *            the data row
	 * @param intProperties
	 *            the int properties
	 * @param itemDescriptorName
	 *            the item descriptor name
	 */
	protected void setIntegerTypeProperties(MutableRepositoryItem item, Map<String, Integer>repositoryPropertiesToTokenIndexMap, String[] dataRow,List<String> intProperties) throws FeedProcessException{
		if(isLoggingDebug()){
			logDebug("BaseRepositoryTools::>setIntegerTypeProperties()::BEGIN");
		}
		String sProp = null;
		for (String integerProperty : intProperties) {
		    if(isLoggingDebug()){
                logDebug("BaseRepositoryTools::>setIntegerTypeProperties():: Setting property: "+integerProperty);
            }
			if(repositoryPropertiesToTokenIndexMap.get(integerProperty)!=null){
    			sProp=dataRow[repositoryPropertiesToTokenIndexMap.get(integerProperty)];
    			if(!StringUtils.isBlank(sProp)&&NumberUtils.isNumber(sProp)){
    			    try{
    				item.setPropertyValue(integerProperty, Integer.parseInt(sProp));
    			    }catch(Exception e){
    			        if(isLoggingError()){
    			            logError("BaseRepositoryTools::>setIntegerTypeProperties()::Exception occured while parsing "+sProp+" into Integer");
    			        }
    			        logError(e);
    			        throw new FeedProcessException(e);
    			    }
    			}else{
    				if(isLoggingError()){
    					logError("BaseRepositoryTools::>setIntegerTypeProperties():: Cannot set Integer type property: "+integerProperty+" on item "+item.getRepositoryId()+", as either the value if empty or it is not a number. Value present:"+sProp);
    				}
    			}
    		} else {
    		    if(isLoggingWarning()){
    		        logWarning("BaseRepositoryTools::>setIntegerTypeProperties():: Column for property:"+integerProperty+" not present in feed");
    		    }
    		}
		}
		if(isLoggingDebug()){
			logDebug("BaseRepositoryTools::>setIntegerTypeProperties()::END");
		}
	}


	protected void setDoubleTypeProperties(MutableRepositoryItem item, Map<String, Integer>repositoryPropertiesToTokenIndexMap, String[] dataRow,List<String> doubleProperties) throws FeedProcessException {
		if(isLoggingDebug()){
			logDebug("BaseRepositoryTools::>setDoubleTypeProperties()::BEGIN");
		}
		String sProp = null;
		for (String doubleProperty : doubleProperties) {
		    if(isLoggingDebug()){
	            logDebug("BaseRepositoryTools::>setDoubleTypeProperties():: Setting Property:"+doubleProperty);
	        }
			if(repositoryPropertiesToTokenIndexMap.get(doubleProperty)!=null){
			sProp=dataRow[repositoryPropertiesToTokenIndexMap.get(doubleProperty)];
			if(!StringUtils.isBlank(sProp)&&NumberUtils.isNumber(sProp)){
			    try{
			        if(isLoggingDebug()){
			            logDebug("BaseRepositoryTools::>setDoubleTypeProperties():: value for property in feed:"+sProp);
			        }
				item.setPropertyValue(doubleProperty, Double.parseDouble(sProp));
			    }catch(Exception e){
                    if(isLoggingError()){
                        logError("BaseRepositoryTools::>setDoubleTypeProperties()::  value "+sProp+" cannot be parsed into Double");
                    }
                    logError(e);
                    throw new FeedProcessException(e);
                }
			}else{
				if(isLoggingDebug()){
					logDebug("BaseRepositoryTools::>setDoubleTypeProperties():: Cannot set double type property: "+doubleProperty+"on item "+item.getRepositoryId()+", as either the value if empty or it is not a number. Value present:"+sProp);
				}
			}
		} else {
		    if(isLoggingWarning()){
		        logWarning("BaseRepositoryTools::>setDoubleTypeProperties():: column for property: "+doubleProperty+" not present in feed");
		    }
		}
		}
		if(isLoggingDebug()){
			logDebug("BaseRepositoryTools::>setDoubleTypeProperties()::END");
		}
	}

	/**
	 * Sets the date type properties.
	 *
	 * @param repository
	 *            the repository
	 * @param item
	 *            the item
	 * @param repositoryPropertiesToTokenIndexMap
	 *            the repository properties to token index map
	 * @param dataRow
	 *            the data row
	 * @param dateProperties
	 *            the date properties
	 * @param itemDescriptorName
	 *            the item descriptor name
	 * @throws FeedProcessException
	 *             the feed process exception
	 */
	protected void setDateTypeProperties(MutableRepositoryItem item, Map<String, Integer>repositoryPropertiesToTokenIndexMap, String[] dataRow,List<String> dateProperties) throws FeedProcessException{
		if(isLoggingDebug()){
			logDebug("BaseRepositoryTools::>setDateTypeProperties()::BEGIN");
		}
		String sProp = null;
		for (String dateProperty : dateProperties) {
		    if(isLoggingDebug()){
	            logDebug("BaseRepositoryTools::>setDateTypeProperties():: Setting property:"+dateProperty);
	        }
			if(repositoryPropertiesToTokenIndexMap.get(dateProperty)!=null){
			sProp=dataRow[repositoryPropertiesToTokenIndexMap.get(dateProperty)];
			if(!StringUtils.isBlank(sProp)){
				try {
				    if(isLoggingDebug()){
			            logDebug("BaseRepositoryTools::>setDateTypeProperties():: value present in feed:"+sProp);
			        }
					Date dateObj = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(sProp);
					item.setPropertyValue(dateProperty, dateObj);
				} catch (ParseException e) {
					if(isLoggingError()){
						logError("BaseRepositoryTools::>setDateTypeProperties():: An Error occured while parsing Date:"+sProp);
					}
					 logError(e);
					throw new FeedProcessException(e);
				}
			} else {
			    if(isLoggingDebug()){
			        logDebug("BaseRepositoryTools::>setDateTypeProperties():: value for property null in feed");
			    }
			}
		} else {
		    if(isLoggingError()){
		        logError("BaseRepositoryTools::>setDateTypeProperties():: column for property:"+dateProperty+" not present in feed file");
		    }
		}
		}
		if(isLoggingDebug()){
			logDebug("BaseRepositoryTools::>setDateTypeProperties()::END");
		}
	}


	/**
	 * Sets the List type properties.
	 *
	 * @param repository
	 *            the repository
	 * @param item
	 *            the item
	 * @param repositoryPropertiesToTokenIndexMap
	 *            the repository properties to token index map
	 * @param dataRow
	 *            the data row
	 * @param intProperties
	 *            the int properties
	 * @param itemDescriptorName
	 *            the item descriptor name
	 */
	protected void setListTypeProperties(MutableRepository repository, MutableRepositoryItem item, Map<String, Integer>repositoryPropertiesToTokenIndexMap, String[] dataRow,List<String> listProperties, String itemDescriptorName ){
		if(isLoggingDebug()){
			logDebug("BaseRepositoryTools::>setListTypeProperties()::BEGIN");
		}
		String sProp = null;
		for (String listProperty : listProperties) {
		    if(isLoggingDebug()){
	            logDebug("BaseRepositoryTools::>setListTypeProperties():: setting value for property:"+listProperty);
	        }
			if(repositoryPropertiesToTokenIndexMap.get(listProperty)!=null){
    			sProp=dataRow[repositoryPropertiesToTokenIndexMap.get(listProperty)];
    			if(!StringUtils.isBlank(sProp)){
    			    if(isLoggingDebug()){
    	                logDebug("BaseRepositoryTools::>setListTypeProperties():: value for property:"+listProperty+ ", in feed "+sProp);
    	            }
    			    ArrayList<String> lstPoperties =new ArrayList<String>();
    				String[] itemIds = sProp.split(",");
    				for(String id:itemIds){
    					lstPoperties.add(id.trim());
    				}
    				if(lstPoperties!=null && !lstPoperties.isEmpty()){
    					item.setPropertyValue(listProperty, lstPoperties);
    				}
    			}else{
    				if(isLoggingDebug()){
    					logDebug("BaseRepositoryTools::>setListTypeProperties():: Cannot set list type property: "+listProperty+"on item "+item.getRepositoryId()+", if the value is empty. Value present:"+sProp);
    				}
    			}
    		} else {
    		    if(isLoggingError()){
    		        logError("BaseRepositoryTools::>setListTypeProperties():: column for property: "+listProperty+" not present in feed file");
    		    }
    		}
		}
		if(isLoggingDebug()){
			logDebug("BaseRepositoryTools::>setListTypeProperties()::END");
		}
	}

	/**
	 * Sets the catalog to Item.
	 *
	 * @param mutableRepository
	 *            the repository
	 * @param item
	 *            the item
	 * @param repositoryPropertiesToTokenIndexMap
	 *            the repository properties to token index map
	 * @param dataRow
	 *            the data row
	 * @param intProperties
	 *            the int properties
	 * @param itemDescriptorName
	 *            the item descriptor name
	 */
	protected void setCatalogToItem(MutableRepository mutableRepository,Repository repository, MutableRepositoryItem item,String catIds, String catalogId, String catalogPropertyName) throws FeedProcessException{
		if(isLoggingDebug()){
			logDebug("BaseRepositoryTools::>setCatalogToItem()::BEGIN");
		}
		try {
			if(repository.getItem(catalogId, CATALOG_ITEM_DESCRIPTOR)!=null){
			    MutableRepositoryItem catalogItem = mutableRepository.getItemForUpdate(catalogId, CATALOG_ITEM_DESCRIPTOR);
			    String[] itemIds = catIds.split(",");
			    for(String id : itemIds){
			    	id=id.trim();
			        if(repository.getItem(id,CATEGORY_ITEM_DESCRIPTOR)!=null){
			            MutableRepositoryItem catItem = mutableRepository.getItemForUpdate(id, CATEGORY_ITEM_DESCRIPTOR);
                        Map<MutableRepositoryItem, MutableRepositoryItem> parentCategoriesForCatalogMap = new HashMap<MutableRepositoryItem, MutableRepositoryItem>();
                        parentCategoriesForCatalogMap.put(catalogItem, item);
                        catItem.setPropertyValue(catalogPropertyName, parentCategoriesForCatalogMap);
			        }

			    }

			}else{
				if(isLoggingDebug()){
					logDebug("BaseRepositoryTools::>setCatalogToItem()::cannot find catalog with id:"+catalogId);
				}
			}
		} catch (RepositoryException e) {
			 logError(e);
			throw new FeedProcessException(e);
		}

		if(isLoggingDebug()){
			logDebug("BaseRepositoryTools::>setCatalogToItem()::END");
		}
	}

	/**
	 * Sets the item type single properties.
	 *
	 * @param mutableRepository
	 *            the repository
	 * @param item
	 *            the item
	 * @param repositoryItemPropertiesToTokenIndexMap
	 *            the repository item properties to token index map
	 * @param itemTypeSinglePropertiesMap
	 *            the item type single properties map
	 * @param dataRow
	 *            the data row
	 * @throws FeedProcessException
	 *             the feed process exception
	 */
	protected void setItemTypeSingleProperties(MutableRepository mutableRepository, Repository repository, MutableRepositoryItem item, Map<String, Integer>repositoryItemPropertiesToTokenIndexMap,Map<String, String> itemTypeSinglePropertiesMap, String[] dataRow, List<String> errorList) throws FeedProcessException{
		for (Map.Entry<String,String> entry : itemTypeSinglePropertiesMap.entrySet()) {
			if(repositoryItemPropertiesToTokenIndexMap.get(entry.getKey())!=null){
				setItemTypeProperty(mutableRepository, repository, item, dataRow[repositoryItemPropertiesToTokenIndexMap.get(entry.getKey())], entry.getValue(), entry.getKey(), errorList);
			}
		}
	}

	/**
	 * Sets the item type list properties.
	 *
	 * @param mutableRepository
	 *            the repository
	 * @param item
	 *            the item
	 * @param repositoryItemPropertiesToTokenIndexMap
	 *            the repository item properties to token index map
	 * @param itemTypeListPropertiesMap
	 *            the item type list properties map
	 * @param dataRow
	 *            the data row
	 * @throws FeedProcessException
	 *             the feed process exception
	 */
	protected void setItemTypeListProperties(MutableRepository mutableRepository, Repository repository, MutableRepositoryItem item, Map<String, Integer>repositoryItemPropertiesToTokenIndexMap,Map<String, String> itemTypeListPropertiesMap, String[] dataRow, List<String> errorList) throws FeedProcessException{
		for (Map.Entry<String,String> entry : itemTypeListPropertiesMap.entrySet()) {
			if(repositoryItemPropertiesToTokenIndexMap.get(entry.getKey())!=null){
				 setItemTypeProperties(mutableRepository,repository, item, dataRow[repositoryItemPropertiesToTokenIndexMap.get(entry.getKey())], entry.getValue(), entry.getKey(), errorList);
			}
		}
	}

	/**
	 * Sets the item type properties.
	 *
	 * @param mutableRespository
	 *            the repository
	 * @param item
	 *            the item
	 * @param itemListIds
	 *            the item list ids
	 * @param itemDescriptorName
	 *            the item descriptor name
	 * @param propertyName
	 *            the property name
	 * @throws FeedProcessException
	 *             the feed process exception
	 */
	protected void setItemTypeProperties(MutableRepository mutableRespository, Repository repository, MutableRepositoryItem item, String itemListIds, String itemDescriptorName, String propertyName, List<String> errorList) throws FeedProcessException{
		if(isLoggingDebug()){
			logDebug("BaseRepositoryTools::>setItemTypeProperties()::BEGIN");
		}
		String[] itemIds = itemListIds.split(",");
		List<String> itemsList = new LinkedList<String>(Arrays.asList(itemIds));
		if(enableExistingItmNtProcess){
			List<RepositoryItem> items = (List<RepositoryItem>) item.getPropertyValue(propertyName);
			List<RepositoryItem> removeItems = new ArrayList<RepositoryItem>();
			List<String> childItemsList = new ArrayList<String>();
			
			for(RepositoryItem childItem:items){
				childItemsList.add(childItem.getRepositoryId());
				if(!itemsList.contains(childItem.getRepositoryId())){
					removeItems.add(childItem);
				}
			}
			for(String id:itemIds){
				if(childItemsList.contains(id)){
					int index= itemsList.indexOf(id);
					itemsList.remove(index);
				}
			}
			
			for(RepositoryItem removeItem : removeItems){
				if(itemsList.contains(removeItem.getRepositoryId())){
					int index= itemsList.indexOf(removeItem.getRepositoryId());
					itemsList.remove(index);	
				}
				items.remove(removeItem);
			}
			
			MutableRepositoryItem itemExists = null;
			StringBuilder err = new StringBuilder();
			RepositoryItem rItem = null;
			for(String id : itemsList){
				id=id.trim();
				if(!StringUtils.isBlank(id)){
					id=id.trim();
					try {
						rItem = repository.getItem(id, itemDescriptorName);
						if(rItem!=null){
							//itemExists = mutableRespository.getItemForUpdate(id, itemDescriptorName);
							items.add(rItem);
							rItem=null;
						}else{
						    err.append(id).append(",");
						}
					} catch (RepositoryException e) {
						 logError(e);
						if(isLoggingDebug()){
							logDebug("BaseRepositoryTools::>setItemTypeProperties():: An Error occured while fetching Item with id:"+id+" of type:"+itemDescriptorName);
						}
						throw new FeedProcessException(e);
					}
				}
			}
			if(err.length()>0){
			    errorList.add("Items with id:"+err.toString()+" of type:"+itemDescriptorName+" could not be found in repository. So not setting on property:"+propertyName+" on item with id:"+item.getRepositoryId());
			}
			
			
			
		} else {
			
			ArrayList<MutableRepositoryItem> repoItems = new ArrayList<MutableRepositoryItem>();
			MutableRepositoryItem itemExists = null;
			StringBuilder err = new StringBuilder();
			RepositoryItem rItem = null;
			for(String id : itemIds){
				id=id.trim();
				if(!StringUtils.isBlank(id)){
					id=id.trim();
					try {
						rItem = repository.getItem(id, itemDescriptorName);
						if(rItem!=null){
							itemExists = mutableRespository.getItemForUpdate(id, itemDescriptorName);
							if(itemExists!=null){
								repoItems.add(itemExists);
								itemExists=null;
							}else{
								if(isLoggingDebug()){
									logDebug("BaseRepositoryTools::>setItemTypeProperties()::Item with id:"+id+" of type"+itemDescriptorName+" does not exist");
								}
							}
							rItem=null;
						}else{
						    err.append(id).append(",");
						}
					} catch (RepositoryException e) {
						 logError(e);
						if(isLoggingDebug()){
							logDebug("BaseRepositoryTools::>setItemTypeProperties():: An Error occured while fetching Item with id:"+id+" of type:"+itemDescriptorName);
						}
						throw new FeedProcessException(e);
					}
				}
			}
			if(err.length()>0){
			    errorList.add("Items with id:"+err.toString()+" of type:"+itemDescriptorName+" could not be found in repository. So not setting on property:"+propertyName+" on item with id:"+item.getRepositoryId());
			}
			if(!repoItems.isEmpty()){
				item.setPropertyValue(propertyName, repoItems);
			}
		}
		
	}

	/**
	 * Sets the item type property.
	 *
	 * @param mutableRepository
	 *            the repository
	 * @param item
	 *            the item
	 * @param id
	 *            the id
	 * @param itemDescriptorName
	 *            the item descriptor name
	 * @param propertyName
	 *            the property name
	 * @throws FeedProcessException
	 *             the feed process exception
	 */
	protected void setItemTypeProperty(MutableRepository mutableRepository, Repository repository, MutableRepositoryItem item, String id, String itemDescriptorName, String propertyName, List<String> errorList) throws FeedProcessException{
		if(isLoggingDebug()){
			logDebug("BaseRepositoryTools::>setItemTypeProperty()::BEGIN || property"+propertyName+" id:"+id+" itemDescriptor"+itemDescriptorName);
		}
		
		
		if(!StringUtils.isBlank(id)){
			
			id =id.trim();
			if(enableExistingItmNtProcess){
				if(null!=item.getPropertyValue(propertyName)){
					RepositoryItem existingMappingItem = (RepositoryItem) item.getPropertyValue(propertyName);
					if(!StringUtils.isBlank(id)&& id.equals(existingMappingItem.getRepositoryId())){
						return;
					}
				} else {
					RepositoryItem rItem = null;
					try {
						rItem = repository.getItem(id, itemDescriptorName);
						if(rItem!=null){
							item.setPropertyValue(propertyName, rItem);
						} else{
					          errorList.add("Items with id:"+id+" of type:"+itemDescriptorName+" could not be found in repository. So not setting on property:"+propertyName+" on item with id:"+item.getRepositoryId());
						}
					} catch (RepositoryException e) {

						 logError(e);
					    errorList.add(new StringBuilder().append("An error occured while fetching item with id:").append(id).append(" of type:").append(itemDescriptorName).append(", so not setting property:").append(propertyName).append(" on item:").append(item.getRepositoryId()).append(" of type:").append(item.getItemDisplayName()).toString());
						if(isLoggingDebug()){
							logDebug("BaseRepositoryTools::>setItemTypeProperty():: "+new StringBuilder().append("An error occured while fetching item with id:").append(id).append(" of type:").append(itemDescriptorName).append(", so not setting property:").append(propertyName).append(" on item:").append(item.getRepositoryId()).append(" of type:").append(item.getItemDisplayName()).toString());
						}
						throw new FeedProcessException(e);
					
					}
				}
				
			} else {
				MutableRepositoryItem itemExists = null;
				RepositoryItem rItem = null;
					try {
						rItem = repository.getItem(id, itemDescriptorName);
						if(rItem!=null){
							itemExists = mutableRepository.getItemForUpdate(id, itemDescriptorName);
							if(itemExists!=null){
								item.setPropertyValue(propertyName, itemExists);
							}else{
								if(isLoggingDebug()){
									logDebug("BaseRepositoryTools::>setItemTypeProperty()::No item exists with id:"+id+" of type:"+itemDescriptorName);
								}
							}
						}else{
					          errorList.add("Items with id:"+id+" of type:"+itemDescriptorName+" could not be found in repository. So not setting on property:"+propertyName+" on item with id:"+item.getRepositoryId());
						}

					} catch (RepositoryException e) {
						 logError(e);
					    errorList.add(new StringBuilder().append("An error occured while fetching item with id:").append(id).append(" of type:").append(itemDescriptorName).append(", so not setting property:").append(propertyName).append(" on item:").append(item.getRepositoryId()).append(" of type:").append(item.getItemDisplayName()).toString());
						if(isLoggingDebug()){
							logDebug("BaseRepositoryTools::>setItemTypeProperty():: "+new StringBuilder().append("An error occured while fetching item with id:").append(id).append(" of type:").append(itemDescriptorName).append(", so not setting property:").append(propertyName).append(" on item:").append(item.getRepositoryId()).append(" of type:").append(item.getItemDisplayName()).toString());
						}
						throw new FeedProcessException(e);
					}
			}
			
			
		} else {
		    if(isLoggingDebug()){
		        logDebug("BaseRepositoryTools::>setItemTypeProperty():: value for Id is null");
		    }
		}
			if(isLoggingDebug()){
				logDebug("BaseRepositoryTools::>setItemTypeProperty()::END");
			}

	}

	/**
	 * Gets the type index.
	 *
	 * @param header
	 *            the header
	 * @return the type index
	 */
	protected int getTypeIndex(String[] header){
		for(int i=0; i<header.length; i++){
			if(header[i].equalsIgnoreCase("type")){
				return i;
			}
		}
		return -1;
	}


    /**
     * Gets the repository.
     *
     * @return the repository
     */
    public Repository getRepository() {
        return repository;
    }

    /**
     * Sets the repository.
     *
     * @param repository
     *            the new repository
     */
    public void setRepository(Repository repository) {
        this.repository = repository;
    }

    /**
     * Gets the string properties.
     *
     * @return the string properties
     */
    public List<String> getStringProperties() {
        return stringProperties;
    }

    /**
     * Sets the string properties.
     *
     * @param stringProperties
     *            the new string properties
     */
    public void setStringProperties(List<String> stringProperties) {
        this.stringProperties = stringProperties;
    }

    /**
     * Gets the boolean properties.
     *
     * @return the boolean properties
     */
    public List<String> getBooleanProperties() {
        return booleanProperties;
    }

    /**
     * Sets the boolean properties.
     *
     * @param booleanProperties
     *            the new boolean properties
     */
    public void setBooleanProperties(List<String> booleanProperties) {
        this.booleanProperties = booleanProperties;
    }

    /**
     * Gets the int properties.
     *
     * @return the int properties
     */
    public List<String> getIntProperties() {
        return intProperties;
    }

    /**
     * Sets the int properties.
     *
     * @param intProperties
     *            the new int properties
     */
    public void setIntProperties(List<String> intProperties) {
        this.intProperties = intProperties;
    }

    /**
     * Gets the date properties.
     *
     * @return the date properties
     */
    public List<String> getDateProperties() {
        return dateProperties;
    }

    /**
     * Sets the date properties.
     *
     * @param dateProperties
     *            the new date properties
     */
    public void setDateProperties(List<String> dateProperties) {
        this.dateProperties = dateProperties;
    }

    /**
     * Gets the item type list properties map.
     *
     * @return the item type list properties map
     */
    public Map<String, String> getItemTypeListPropertiesMap() {
        return itemTypeListPropertiesMap;
    }

    /**
     * Sets the item type list properties map.
     *
     * @param itemTypeListPropertiesMap
     *            the item type list properties map
     */
    public void setItemTypeListPropertiesMap(
            Map<String, String> itemTypeListPropertiesMap) {
        this.itemTypeListPropertiesMap = itemTypeListPropertiesMap;
    }

    /**
     * Gets the item type single properties map.
     *
     * @return the item type single properties map
     */
    public Map<String, String> getItemTypeSinglePropertiesMap() {
        return itemTypeSinglePropertiesMap;
    }

    /**
     * Sets the item type single properties map.
     *
     * @param itemTypeSinglePropertiesMap
     *            the item type single properties map
     */
    public void setItemTypeSinglePropertiesMap(
            Map<String, String> itemTypeSinglePropertiesMap) {
        this.itemTypeSinglePropertiesMap = itemTypeSinglePropertiesMap;
    }
    /**
     * @return the listTypeProperties
     */
    public List<String> getListTypeProperties() {
        return listTypeProperties;
    }

    /**
     * @param listTypeProperties
     *            the listTypeProperties to set
     */
    public void setListTypeProperties(List<String> listTypeProperties) {
        this.listTypeProperties = listTypeProperties;
    }

	public List<String> getDoubleProperties() {
		return doubleProperties;
	}

	public void setDoubleProperties(List<String> doubleProperties) {
		this.doubleProperties = doubleProperties;
	}

	public List<String> getIgnoreIfDataExistsProperties() {
		return ignoreIfDataExistsProperties;
	}

	public void setIgnoreIfDataExistsProperties(
			List<String> ignoreIfDataExistsProperties) {
		this.ignoreIfDataExistsProperties = ignoreIfDataExistsProperties;
	}

	public boolean isEnableExistingItmNtProcess() {
		return enableExistingItmNtProcess;
	}

	public void setEnableExistingItmNtProcess(boolean enableExistingItmNtProcess) {
		this.enableExistingItmNtProcess = enableExistingItmNtProcess;
	}


	public String getItemDescriptorName() {
		return itemDescriptorName;
	}


	public void setItemDescriptorName(String itemDescriptorName) {
		this.itemDescriptorName = itemDescriptorName;
	}


	public String getSubTypeDefinationProperty() {
		return subTypeDefinationProperty;
	}


	public void setSubTypeDefinationProperty(String subTypeDefinationProperty) {
		this.subTypeDefinationProperty = subTypeDefinationProperty;
	}


}
